/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-26 16:27:32
 * @LastEditTime: 2021-08-04 08:30:59
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#include <string.h>
#include "sdkconfig.h"
#include "parameters.h"
#include "ft_assert.h"
#include "dw_i2c.h"
#include "dw_i2c_hw.h"

#define EEPROM_LEN  128
typedef struct
{
    I2cCtrl slave;
    boolean firstWrite;
    u8      buf[EEPROM_LEN];
    u32     bufIdx;
} I2cEepromSlave;

I2cEepromSlave slaveEeprom;

void I2cEeSlaveWriteReceivedCB(void *pPara)
{
    FT_ASSERTVOID(pPara);
    I2cCtrl *pCtrl = (I2cCtrl *)pPara;
    I2cEepromSlave *pEeprom = (I2cEepromSlave *)pCtrl->prv;

    if (pEeprom->firstWrite)  
    {
        pEeprom->bufIdx = pCtrl->curTrans; /* send slave addr in first write */
        pEeprom->firstWrite = FALSE;
    } 
    else
    {
        I2C_INFO("buf[0x%x]: 0x%x", pEeprom->bufIdx, pCtrl->curTrans);
        pEeprom->buf[pEeprom->bufIdx++] = pCtrl->curTrans;
    }

    return;
}

void I2cEeSlaveReadRequested(void *pPara)
{
    FT_ASSERTVOID(pPara);
    I2cCtrl *pCtrl = (I2cCtrl *)pPara;
    I2cEepromSlave *pEeprom = (I2cEepromSlave *)pCtrl->prv;

    /*
    * Do not increment bufIdx here, because we don't know if
    * this byte will be actually used. Read Linux I2C slave docs
    * for details.
    */
    pCtrl->curTrans = pEeprom->buf[pEeprom->bufIdx];

    return;
}

void I2cEeSlaveReadProcessed(void *pPara)
{
    FT_ASSERTVOID(pPara);
    I2cCtrl *pCtrl = (I2cCtrl *)pPara;
    I2cEepromSlave *pEeprom = (I2cEepromSlave *)pCtrl->prv;

    I2C_INFO("Slave ReadProcessed");

    /* The previous byte made it to the bus, get next one */
    pEeprom->bufIdx++;
    I2cEeSlaveReadRequested(pPara);/* fallthrough */

    return;
}

void I2cEeSlaveStop(void *pPara)
{
    FT_ASSERTVOID(pPara);
    I2cCtrl *pCtrl = (I2cCtrl *)pPara;
    I2cEepromSlave *pEeprom = (I2cEepromSlave *)pCtrl->prv;

    I2C_INFO("Slave Stop");

    pEeprom->firstWrite = TRUE;
    return;
}

void I2cEeSlaveWriteRequested(void *pPara)
{
    FT_ASSERTVOID(pPara);
    I2cCtrl *pCtrl = (I2cCtrl *)pPara;
    I2cEepromSlave *pEeprom = (I2cEepromSlave *)pCtrl->prv;

    I2C_INFO("Slave WriteRequested");

    I2cEeSlaveStop(pPara);
    return;    
}

u32 I2cEeSlaveInit()
{
    I2cEepromSlave *pEeprom = &slaveEeprom;
    I2cCtrl *pCtrl = &pEeprom->slave;
    u32 i2cId = I2C_INSTANCE_1;
    u32 ret = I2C_SUCCESS;

    memset(pEeprom, 0, sizeof(I2cEepromSlave));

    pCtrl->config = *I2cLookupConfig(i2cId);
    ret = I2cInit(pCtrl, &pCtrl->config);
    if (I2C_SUCCESS != ret)
        return ret;

    pCtrl->prv = pEeprom;

    pEeprom->firstWrite = TRUE;
    I2cRegisterEvtCallback(pCtrl, I2C_EVT_SLAVE_READ_REQUESTED, I2cEeSlaveReadRequested);
    I2cRegisterEvtCallback(pCtrl, I2C_EVT_SLAVE_WRITE_REQUESTED, I2cEeSlaveWriteRequested);
    I2cRegisterEvtCallback(pCtrl, I2C_EVT_SLAVE_READ_PROCESSED, I2cEeSlaveReadProcessed);
    I2cRegisterEvtCallback(pCtrl, I2C_EVT_SLAVE_WRITE_RECEIVED, I2cEeSlaveWriteReceivedCB);
    I2cRegisterEvtCallback(pCtrl, I2C_EVT_SLAVE_STOP, I2cEeSlaveStop);

    I2cDumpInfo(pCtrl);

    return ret;
}

void I2cEeSlaveReadBuf()
{
    I2cEepromSlave *pEeprom = &slaveEeprom;
    I2cCtrl *pCtrl = &pEeprom->slave;

    FtDumpHexByte(pEeprom->buf, EEPROM_LEN);
}